package com.hqd.ch03.v50.context.support;

import com.hqd.ch03.v50.beans.BeansException;
import com.hqd.ch03.v50.config.BeanPostProcessor;
import com.hqd.ch03.v50.config.EmbeddedValueResolver;
import com.hqd.ch03.v50.config.StringValueResolver;
import com.hqd.ch03.v50.context.ApplicationContextAware;
import com.hqd.ch03.v50.context.ConfigurableApplicationContext;

import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;

public class ApplicationContextAwareProcessor implements BeanPostProcessor {

    private final ConfigurableApplicationContext applicationContext;

    private final StringValueResolver embeddedValueResolver;


    /**
     * Create a new ApplicationContextAwareProcessor for the given context.
     */
    public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
        this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
    }


    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (!(bean instanceof ApplicationContextAware)) {
            return bean;
        }

        AccessControlContext acc = null;

        if (System.getSecurityManager() != null) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        if (acc != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareInterfaces(bean);
                return null;
            }, acc);
        } else {
            invokeAwareInterfaces(bean);
        }

        return bean;
    }

    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof ApplicationContextAware) {
            ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
        }
    }

}
